/**
 * 
 */
package com.blazegame.logging.async;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.log4j.Logger;

/**
 * FIXME 输出日志的速度是否大于产生日志的速度 饥饿策略
 * 
 * @author JackChu
 * @version 2011-7-8 下午04:55:41
 */
public class LoggerExecutor {

	private static final Logger logger = Logger.getLogger(LoggerExecutor.class);

	private static ExecutorService executor = Executors.newSingleThreadExecutor();

	private static BlockingQueue<LogTask> logQueue = new LinkedBlockingQueue<LogTask>();

	private static LogWorker logWorker = new LogWorker();

	private static boolean isWorkerStop = false;

	public static void put(LogTask task) {
		if (isWorkerStop) {
			logger.fatal("########################logger executor is shutdown######################");
			return;
		}
		try {
			logQueue.put(task);
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
			logger.error("Got an InterruptedException while put log task", e);
		} catch (Exception e) {
			logger.error("Got an Exception while put log task", e);
		}

		// int logSize = logQueue.size();
		// if (logSize > 300) {
		// logger
		// .fatal("logger message size greater than 300,size:"
		// + logSize);
		// }
	}

	static {
		executor.execute(logWorker);
	}

	public LoggerExecutor() {
	}

	private final static class LogWorker implements Runnable {
		@Override
		public void run() {
			LogTask logTask = null;
			while (!isWorkerStop && !Thread.currentThread().isInterrupted()) {
				try {
					logTask = logQueue.take();
					logTask.log();
				} catch (InterruptedException e) {
					isWorkerStop = true;
					Thread.currentThread().interrupt();
					logger.error("Got an InterruptedException while take log task", e);
				}
				if (logQueue.size() == 0) {
					logger.debug("===============================");
					logger.debug("logger message handle finish");
					logger.debug("===============================");
				}
			}

		}

		public void interrupt() {
			Thread.currentThread().interrupt();
		}
	}

	public static void shutdown() {
		//
		while (logQueue.size() > 0) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				logger.error("Got an Exception while shutdown log task", e);
			}
		}

		logWorker.interrupt();

		executor.shutdown();
	}
}
